using System;
using System.Collections.Generic;
using Nop.Core;
using Nop.Core.Domain.Common;

namespace Nop.Services.Common
{
    public static class AddressExtentions
    {
        static string addrFormat = "{1}-{0}"; 

        /// <summary>
        /// Find an address
        /// </summary>
        /// <param name="source">Source</param>
        /// <param name="firstName">First name</param>
        /// <param name="lastName">Last name</param>
        /// <param name="phoneNumber">Phone number</param>
        /// <param name="email">Email</param>
        /// <param name="faxNumber">Fax number</param>
        /// <param name="company">Company</param>
        /// <param name="address1">Address 1</param>
        /// <param name="address2">Address 2</param>
        /// <param name="city">City</param>
        /// <param name="stateProvinceId">State/province identifier</param>
        /// <param name="zipPostalCode">Zip postal code</param>
        /// <param name="countryId">Country identifier</param>
        /// <returns>Address</returns>
        public static Address FindAddress(this List<Address> source,
            string firstName, string lastName, string phoneNumber, string cellPhoneNumber,
            string email, string faxNumber, string company, string address1,
            string address2, string city, int? stateProvinceId,
            string zipPostalCode, int? countryId)
        {
            return source.Find((a) => ((String.IsNullOrEmpty(a.FirstName) && String.IsNullOrEmpty(firstName)) || (a.FirstName != null && a.FirstName.Equals(firstName, StringComparison.CurrentCultureIgnoreCase))) &&
                ((String.IsNullOrEmpty(a.LastName) && String.IsNullOrEmpty(lastName)) || (a.LastName != null && a.LastName.Equals(lastName, StringComparison.CurrentCultureIgnoreCase))) &&
                ((String.IsNullOrEmpty(a.PhoneNumber) && String.IsNullOrEmpty(phoneNumber)) || (a.PhoneNumber != null && a.PhoneNumber.Equals(phoneNumber, StringComparison.CurrentCultureIgnoreCase))) &&
                ((String.IsNullOrEmpty(a.CellPhoneNumber) && String.IsNullOrEmpty(cellPhoneNumber)) || (a.CellPhoneNumber != null && a.CellPhoneNumber.Equals(cellPhoneNumber, StringComparison.CurrentCultureIgnoreCase))) &&
                ((String.IsNullOrEmpty(a.Email) && String.IsNullOrEmpty(email)) || (a.Email != null && a.Email.Equals(email, StringComparison.CurrentCultureIgnoreCase))) &&
                ((String.IsNullOrEmpty(a.FaxNumber) && String.IsNullOrEmpty(faxNumber)) || (a.FaxNumber != null && a.FaxNumber.Equals(faxNumber, StringComparison.CurrentCultureIgnoreCase))) &&
                ((String.IsNullOrEmpty(a.Company) && String.IsNullOrEmpty(company)) || (a.Company != null && a.Company.Equals(company, StringComparison.CurrentCultureIgnoreCase))) &&
                ((String.IsNullOrEmpty(a.Address1) && String.IsNullOrEmpty(address1)) || (a.Address1 != null && a.Address1.Equals(address1, StringComparison.CurrentCultureIgnoreCase))) &&
                ((String.IsNullOrEmpty(a.Address2) && String.IsNullOrEmpty(address2)) || (a.Address2 != null && a.Address2.Equals(address2, StringComparison.CurrentCultureIgnoreCase))) &&
                ((String.IsNullOrEmpty(a.City) && String.IsNullOrEmpty(city)) || (a.City != null && a.City.Equals(city, StringComparison.CurrentCultureIgnoreCase))) &&
                ((a.StateProvinceId.IsNullOrDefault() && stateProvinceId.IsNullOrDefault()) || a.StateProvinceId == stateProvinceId) &&
                ((String.IsNullOrEmpty(a.ZipPostalCode) && String.IsNullOrEmpty(zipPostalCode)) || (a.ZipPostalCode != null && a.ZipPostalCode.Replace(" ", String.Empty).Equals(zipPostalCode.Replace(" ", String.Empty), StringComparison.CurrentCultureIgnoreCase))) &&
                ((a.CountryId.IsNullOrDefault() && countryId.IsNullOrDefault()) || a.CountryId == countryId));
        }

        /// <summary>
        /// Get company name, or cutomer name if company name is empty.
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public static string GetCompanyNameOrFullName(this Address address)
        {
            if (address == null)
                throw new ArgumentNullException("address");

            return String.IsNullOrWhiteSpace(address.Company) ? String.Format("{0} {1}", address.FirstName, address.LastName) : address.Company;
        }

        /// <summary>
        /// Generate a well-formatted address
        /// </summary>
        /// <param name="address"></param>
        /// <returns>Address string</returns>
        public static string FormattedAddress(this Address address, bool multipleLine = false)
        {
            var sb = new System.Text.StringBuilder();
            bool hasAddr1 = !String.IsNullOrWhiteSpace(address.Address1);
            bool hasAddr2 = !String.IsNullOrWhiteSpace(address.Address2);
            // TODO: support multiple counties.
            
            if (multipleLine)
            {
                if (hasAddr1)
                    sb.AppendLine(address.Address1);
                if (hasAddr2)
                    sb.AppendLine(address.Address2);
            }
            else
            {
                if (hasAddr1 && hasAddr2)
                    sb.AppendFormat(addrFormat, address.Address1, address.Address2);
                else if (hasAddr1)
                {
                    sb.Append(address.Address1);
                }
            }

            if (!String.IsNullOrWhiteSpace(address.City))
            {
                if (multipleLine)
                {
                    sb.AppendLine(address.City);
                }
                else
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(", ");
                    }
                    sb.Append(address.City);
                }
            }

            if (address.StateProvince != null)
            {
                if (multipleLine)
                {
                    sb.AppendLine(address.StateProvince.Name);
                }
                else
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(", ");
                    }
                    sb.Append(address.StateProvince.Name);
                }
            }

            if (!String.IsNullOrWhiteSpace(address.ZipPostalCode))
            {
                if (multipleLine)
                {
                    sb.AppendLine(address.ZipPostalCode);
                }
                else
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(", ");
                    }
                    sb.Append(address.ZipPostalCode);
                }
            }
            return sb.ToString();
        }

        /// <summary>
        /// Generate a well-formatted address
        /// </summary>
        /// <param name="address"></param>
        /// <returns>Address string</returns>
        public static string FormattedAddressNoSuite(this Address address)
        {
            var sb = new System.Text.StringBuilder();

            if (!String.IsNullOrWhiteSpace(address.Address1))
            {
                string addr1 = address.Address1;
                if (address.Address1.Contains("-"))
                {
                    string[] t = address.Address1.Split('-');
                    if (t.Length == 2)
                    {
                        addr1 = t[1];
                    }
                }
                //string addr = address.Address2 == null ? addr1 : String.Format("{0} {1}", addr1, address.Address2);
                sb.Append(addr1);
            }

            if (!String.IsNullOrWhiteSpace(address.City))
            {
                if (sb.Length > 0)
                {
                    sb.Append(", ");
                }
                sb.Append(address.City);
            }

            if (address.StateProvince != null)
            {
                if (sb.Length > 0)
                {
                    sb.Append(", ");
                }
                sb.Append(address.StateProvince.Name);
            }

            if (!String.IsNullOrWhiteSpace(address.ZipPostalCode))
            {
                if (sb.Length > 0)
                {
                    sb.Append(", ");
                }
                sb.Append(address.ZipPostalCode);
            }
            return sb.ToString();
        }

        /// <summary>
        /// Generate a short address
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public static string FormatAddressShort(this Address address)
        {
            string addressStr;
            if (!String.IsNullOrEmpty(address.Address2))
            {
                addressStr = String.Format(addrFormat, address.Address1, address.Address2);
            }
            else
            {
                addressStr = address.Address1;
            }
            if (!String.IsNullOrEmpty(address.City))
            {
                addressStr += " " + address.City;
            }
            return addressStr;
        }

        /// <summary>
        /// Check if the address type is finally verified.
        /// </summary>
        /// <param name="address">address</param>
        /// <returns></returns>
        public static bool IsAddressTypeVerified(this Address address)
        {
            return address.VerifiedTypeId.HasValue &&
                address.TypeId.HasValue &&
                address.VerifiedType == address.Type;
        }
    }
}
